package com.hzw.saas.common.storage.service;

import java.io.File;
import java.io.InputStream;
import java.util.List;

import com.hzw.saas.common.storage.pojo.FileStorage;
import com.hzw.saas.common.storage.pojo.InxChunkMetadata;
import com.hzw.saas.common.storage.pojo.InxChunkStorage;
import com.hzw.saas.common.storage.pojo.LocChunkStorage;
import com.hzw.saas.common.util.enums.ConflictModeEnum;
import cn.hutool.core.io.IORuntimeException;

/**
 * 分片存储接口
 * 路径参数均支持绝对路径和相对路径，相对路径的根路径为classpath
 *
 * @author zzl
 * @since 04/21/2021
 */
public interface IChunkStorageService {

    /**
     * 获取分片文件
     *
     * @param path 分片路径
     * @return 目标分片文件
     */
    File getChunk(String path);

    /**
     * 获取分片文件
     *
     * @param supPath   父路径
     * @param chunkName 分片名称/分片ID/分片索引
     * @return 目标分片文件
     */
    File getChunk(String supPath, String chunkName);

    /**
     * 检查分片是否存在
     *
     * @param path 分片路径
     * @return true 存在，false 不存在
     */
    boolean exist(String path);

    /**
     * 检查分片是否存在
     *
     * @param supPath   父路径
     * @param chunkName 分片名称/分片ID/分片索引
     * @return true 存在，false 不存在
     */
    boolean exist(String supPath, String chunkName);

    /**
     * 检查分片长度
     *
     * @param path 分片路径
     * @return 文件长度，-1：文件不存在
     */
    long getLength(String path);

    /**
     * 检查分片长度
     *
     * @param supPath   父路径
     * @param chunkName 分片名称/分片ID/分片索引
     * @return 文件长度，-1：文件不存在
     */
    long getLength(String supPath, String chunkName);

    /**
     * 校验分片摘要，MD5
     *
     * @param path       分片路径
     * @param digestType 摘要类型，支持md5,sha1,sha256。为空或其他则默认使用md5
     * @return 摘要16进制字符串, null: 文件不存在
     */
    String getDigest(String path, String digestType);

    /**
     * 校验分片摘要，MD5
     *
     * @param supPath    父路径
     * @param chunkName  分片ID/分片索引
     * @param digestType 摘要类型，支持md5,sha1,sha256。为空或其他则默认使用md5
     * @return 摘要16进制字符串, null: 文件不存在
     */
    String getDigest(String supPath, String chunkName, String digestType);

    /**
     * 保存分片
     *
     * @param supPath
     * @param chunkName
     * @param ins
     */
    void saveChunk(String supPath, String chunkName, InputStream ins);

    /**
     * 保存分片数据，LOC模式
     *
     * @param chunkInfo  分片信息
     * @param chunkBytes 分片数据
     */
    void saveChunk(LocChunkStorage chunkInfo, byte[] chunkBytes);

    /**
     * 保存分片数据，INX模式
     *
     * @param chunkInfo  分片信息
     * @param chunkBytes 分片数据
     */
    void saveChunk(InxChunkStorage chunkInfo, byte[] chunkBytes);

    /**
     * 删除分片
     *
     * @param path 分片路径
     */
    void deleteChunk(String path);

    /**
     * 删除分片
     *
     * @param supPath   父路径
     * @param chunkName 分片ID/分片索引
     */
    void deleteChunk(String supPath, String chunkName);

    /**
     * 删除文件的所有分片
     *
     * @param supPath 父路径
     */
    void deleteChunks(String supPath);

    /**
     * 写入分片操作元数据
     * 请先调用读取分片数据获取已有的元数据信息，避免重要数据被覆盖
     *
     * @param supPath          父路径
     * @param inxChunkMetadata 分片操作元数据
     */
    void writeMetadata(String supPath, InxChunkMetadata inxChunkMetadata);

    /**
     * 读取分片操作元数据
     *
     * @param supPath 父路径
     * @return
     */
    InxChunkMetadata readMetadata(String supPath);

    /**
     * 合并文件分片
     *
     * @param fileInfo      目标文件信息
     * @param chunkSupPath  分片目录路径
     * @param chunkInfoList 分片信息
     * @param delChunks     合并完成后是否删除分片
     * @param mode          同名冲突解决方式
     * @return 合并后的文件
     * @throws IORuntimeException check FileNotFoundException(分片不存在)
     */
    File mergeChunks(FileStorage fileInfo, String chunkSupPath, List<LocChunkStorage> chunkInfoList, boolean delChunks, ConflictModeEnum mode) throws IORuntimeException;

    /**
     * 追加文件分片
     *
     * @param fileInfo      目标文件信息
     * @param chunkSupPath  分片目录路径
     * @param chunkInfoList 分片信息
     * @param delChunks     合并完成后是否删除分片
     * @param mode          同名冲突解决方式
     * @return 合并后的文件
     * @throws IORuntimeException check FileNotFoundException(分片不存在)
     */
    File appendChunks(FileStorage fileInfo, String chunkSupPath, List<LocChunkStorage> chunkInfoList, boolean delChunks, ConflictModeEnum mode) throws IORuntimeException;

    /**
     * @param fileInfo     目标文件信息
     * @param chunkSupPath 分片父路径
     * @param delChunks    合并完成后是否删除分片
     * @param mode         同名冲突解决方式
     * @return 合并后的文件
     * @throws IORuntimeException check FileNotFoundException(分片不存在)
     */
    File mergeChunks(FileStorage fileInfo, String chunkSupPath, boolean delChunks, ConflictModeEnum mode) throws IORuntimeException;

}
